﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;

namespace ECommon
{
    /// <summary>
    /// 字符串工具
    /// </summary>
    public static partial class StringTool
    {
        /// <summary>
        /// 首字母大写
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <returns>转换后的结果</returns>
        public static string FirstLetterUpper(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return source;
            }
            if (source.Length <= 1)
            {
                return source.ToUpper();
            }
            return source.First().ToString().ToUpper() + source.Substring(1);
        }

        /// <summary>
        /// 首字母小写
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <returns>转换后的结果</returns>
        public static string FirstLetterLower(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return source;
            }
            if (source.Length <= 1)
            {
                return source.ToUpper();
            }
            return source.First().ToString().ToLower() + source.Substring(1);
        }

        /// <summary>
        /// 转换字符串为帕斯卡模式
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <param name="separator">字符串分隔符</param>
        /// <returns>转换后的结果</returns>
        public static string ToPascal(string source, char separator = '_')
        {
            if (string.IsNullOrEmpty(source))
            {
                return source;
            }
            List<string> parts = source.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries).ToList();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < parts.Count; i++)
            {
                stringBuilder.Append(FirstLetterUpper(parts[i]));
            }
            return stringBuilder.ToString();
        }



        /// <summary>
        /// 转换字符串为分割符模式
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <param name="separator">字符串分隔符</param>
        /// <returns>转换后的结果</returns>
        public static string ToSeparator(string source, char separator = '_')
        {
            if (string.IsNullOrEmpty(source))
            {
                return source;
            }
            List<char> chars = new List<char>();
            for (int i = 0; i < source.Length; i++)
            {
                if (_upperLetter.Contains(source[i]))
                {
                    if (i != 0)
                    {
                        chars.Add(separator);
                    }
                    chars.Add(source[i].ToString().ToLower()[0]);
                }
                else
                {
                    chars.Add(source[i]);
                }
            }
            return new string(chars.ToArray());
        }

        /// <summary>
        /// 转换字符串为驼峰模式
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <param name="separator">字符串分隔符</param>
        /// <returns>c转换后的结果</returns>
        public static string ToCamel(string source, char separator = '_')
        {
            if (string.IsNullOrEmpty(source))
            {
                return source;
            }
            List<string> parts = source.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries).ToList();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < parts.Count; i++)
            {
                if (i == 0)
                {
                    stringBuilder.Append(FirstLetterLower(parts[i]));
                }
                else
                {
                    stringBuilder.Append(FirstLetterUpper(parts[i]));
                }
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        /// 字节数组转换为字符串
        /// </summary>
        /// <param name="data">字节数组</param>
        /// <returns>转换后的字符串</returns>
        /// <exception cref="ArgumentNullException">参数为空异常</exception>
        public static string GetStringFromByteArray(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data", "字节数据文件为空");
            }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sb.Append(data[i].ToString("x2"));
            }
            return sb.ToString().ToLower();
        }

        /// <summary>
        /// 16进制转2进制
        /// </summary>
        /// <param name="hexNumStr">16进制字符串</param>
        /// <returns>2进制字符串</returns>
        public static string HexToBin(string hexNumStr)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in hexNumStr.ToUpper())
            {
                sb.Append(_hexToBin[c]);
            }
            return sb.ToString();
        }

        /// <summary>
        /// 2进制转16进制
        /// </summary>
        /// <param name="binaryString">二进制字符串</param>
        /// <param name="upperCase">是否大写</param>
        /// <returns>16进制字符串</returns>
        /// <exception cref="ArgumentException">变量异常</exception>
        public static string BinToHex(string binaryString, bool upperCase = true)
        {
            // 检查空值
            if (string.IsNullOrEmpty(binaryString))
                throw new ArgumentException("二进制字符串不能为空");

            // 验证二进制字符串有效性
            foreach (char c in binaryString)
            {
                if (c != '0' && c != '1')
                    throw new ArgumentException("二进制字符串只能包含0和1");
            }
            // 补齐4的倍数长度
            int paddingLength = (4 - binaryString.Length % 4) % 4;
            binaryString = new string('0', paddingLength) + binaryString;
            StringBuilder hexString = new StringBuilder();
            for (int i = 0; i < binaryString.Length; i += 4)
            {
                string nibble = binaryString.Substring(i, 4);
                hexString.Append(_binToHex[nibble]);
            }
            // 处理大小写
            return upperCase ? hexString.ToString() : hexString.ToString().ToLower();

        }

        /// <summary>
        /// 10进制转2进制
        /// </summary>
        /// <param name="decimalString">10进制字符串</param>
        /// <returns>2进制字符串</returns>
        /// <exception cref="ArgumentException">变量异常</exception>
        public static string DecimalToBinary(string decimalString)
        {
            try
            {
                // 尝试转换为整数
                int number = int.Parse(decimalString);
                return Convert.ToString(number, 2);
            }
            catch (FormatException)
            {
                throw new ArgumentException("输入的不是有效的十进制数字");
            }
            catch (OverflowException)
            {
                throw new ArgumentException("数字超出int类型范围");

            }
        }

        /// <summary>
        /// 2进制转10进制
        /// </summary>
        /// <param name="binaryString">2进制字符串</param>
        /// <returns>10进制字符串</returns>
        /// <exception cref="ArgumentException">变量异常</exception>
        public static string BinaryToDecimal(string binaryString)
        {
            try
            {
                // 尝试转换为整数
                int number = Convert.ToInt32(binaryString, 2);
                return number.ToString();
            }
            catch (FormatException)
            {
                throw new ArgumentException("输入的不是有效的二进制数字");
            }
            catch (OverflowException)
            {
                throw new ArgumentException("数字超出int类型范围");
            }
        }

        /// <summary>
        /// 字节集合转换为16进制字符串
        /// </summary>
        /// <param name="byteList">字节集合</param>
        /// <returns>16进制字符串</returns>
        /// <exception cref="ArgumentNullException">字节集合为空异常</exception>
        public static string BytesToHexString(List<byte> byteList)
        {
            if (byteList == null)
            {
                throw new ArgumentNullException("要转换的字节集合为空");
            }
            StringBuilder hexString = new StringBuilder(byteList.Count * 2);
            foreach (byte b in byteList)
            {
                hexString.AppendFormat("{0:X2}", b);
            }
            return hexString.ToString();
        }
        /// <summary>
        /// ASCII转换为16进制字符串
        /// </summary>
        /// <param name="msg">ASCII字符串</param>
        /// <returns>16进制字符串</returns>
        public static string AsciiToHex(string msg)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in msg)
            {
                sb.Append(((int)c).ToString("x2").ToUpper());
            }
            return sb.ToString();
        }

        /// <summary>
        /// 16进制转ASCII字符串
        /// </summary>
        /// <param name="hexString">16进制字符串</param>
        /// <returns>ASCII字符串</returns>
        /// <exception cref="ArgumentException">字符串长不合法抛出异常</exception>
        public static string HexToAscii(string hexString)
        {
            // 检查是否为有效16进制字符串
            if (hexString.Length % 2 != 0)
            {
                throw new ArgumentException("输入字符串长度必须是偶数");
            }

            byte[] bytes = new byte[hexString.Length / 2];
            for (int i = 0; i < hexString.Length; i += 2)
            {
                string hexByte = hexString.Substring(i, 2);
                bytes[i / 2] = Convert.ToByte(hexByte, 16);
            }
            return Encoding.ASCII.GetString(bytes);
        }

        /// <summary>
        /// 验证字符串是否是一个ip地址
        /// </summary>
        /// <param name="ip">ip地址</param>
        /// <returns>验证结果</returns>
        public static bool IsValidIPv4(string ip)
        {
            return IPAddress.TryParse(ip, out IPAddress address) && address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork;
        }

        /// <summary>
        /// 验证字符串是否是一个合法的主机地址
        /// </summary>
        /// <param name="hostStr">主机地址</param>
        /// <returns>验证结果</returns>
        public static bool IsHost(string hostStr)
        {
            if (hostStr.ToLower() == "localhost")
            {
                return true;
            }
            return IsValidIPv4(hostStr);
        }

        /// <summary>
        /// 2进制转16进制
        /// </summary>
        private static Dictionary<char, string> _hexToBin = new Dictionary<char, string>()
        {
            {'0',"0000"},{'1',"0001"},{'2',"0010"},{'3',"0011"},{'4',"0100"},{'5',"0101"},{'6',"0110"},{'7',"0111"},{'8',"1000"},{'9',"1001"},{'A',"1010"},{'B',"1011"},{'C',"1100"},{'D',"1101"},{'E',"1110"},{'F',"1111"}
        };
        /// <summary>
        /// 16进制转2进制
        /// </summary>
        private static Dictionary<string, char> _binToHex = new Dictionary<string, char>()
        {
             {"0000", '0'}, {"0001", '1'}, {"0010", '2'}, {"0011", '3'},
            {"0100", '4'}, {"0101", '5'}, {"0110", '6'}, {"0111", '7'},
            {"1000", '8'}, {"1001", '9'}, {"1010", 'A'}, {"1011", 'B'},
            {"1100", 'C'}, {"1101", 'D'}, {"1110", 'E'}, {"1111", 'F'}
        };

        /// <summary>
        /// upper letter
        /// </summary>
        private static List<char> _upperLetter = new List<char>(){ 'A', 'B', 'C', 'D', 'E', 'F', 'G',
        'H', 'I', 'J', 'K', 'L', 'M', 'N',
        'O', 'P', 'Q', 'R', 'S', 'T', 'U',
        'V', 'W', 'X', 'Y', 'Z'};

        #region 正则表达式部分
        /// <summary>
        /// 正则：全数字判断
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>判断结果</returns>
        public static bool RegexIsNumber(string origin)
        {
            return Regex.IsMatch(origin, @"\d");
        }

        /// <summary>
        /// 正则：获取全部数字
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>数字</returns>
        public static string RegexGetNumber(string origin)
        {
            return Regex.Replace(origin, @"[^\d]", "");
        }

        /// <summary>
        /// 正则：decimal判断
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>判断结果</returns>
        public static bool RegexIsDecimal(string origin)
        {
            return Regex.IsMatch(origin, @"^[+-]?\d*[.]?\d*$");
        }

        /// <summary>
        /// 正则：获取全部decimal
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>decimal</returns>
        public static string RegexGetDecimal(string origin)
        {
            return Regex.Replace(origin, @"[^\d.+-]", "");
        }

        /// <summary>
        /// 正则：全可编辑字符判断
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>判断结果</returns>
        public static bool RegexIsEditable(string origin)
        {
            return Regex.IsMatch(origin, @"[ \da-zA-Z:.+/-]*");
        }

        /// <summary>
        /// 正则：获取全可编辑字符
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>判断结果</returns>
        public static string RegexGetEditable(string origin)
        {
            return Regex.Replace(origin, @"[^ \da-zA-Z:/-]", "");
        }

        /// <summary>
        /// 正则：判定字符串是否为合法手机号码
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>判断结果</returns>
        /// <exception cref="Exception">字符串为空异常</exception>
        public static bool RegexIsPhone(string origin)
        {
            if (origin == null)
            {
                throw new Exception("原始字符串为空");
            }
            origin = origin.Replace("+86", "");
            return Regex.IsMatch(origin, @"^1[3-9]\d{9}$");
        }

        /// <summary>
        /// 正则：判定字符串是否为合法邮箱
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>判定结果</returns>
        public static bool RegexIsEmail(string origin)
        {
            return Regex.IsMatch(origin, @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$");
        }

        /// <summary>
        /// 正则：获取邮箱
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>邮箱</returns>
        public static string RegexGetEmail(string origin)
        {
            return Regex.Replace(origin, @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$", "");
        }

        /// <summary>
        /// 正则：获取手机号码
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>手机号码</returns>
        /// <exception cref="Exception">字符串为空异常</exception>
        public static string RegexGetPhone(string origin)
        {
            if (origin == null)
            {
                throw new Exception("原始字符串为空");
            }
            origin = origin.Replace("+86", "");
            return Regex.Replace(origin, @"^1[3-9]\d{9}$", "");
        }

        /// <summary>
        /// 正则：判定字符串是否为合法Ip地址
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>判断结果</returns>
        public static bool RegexIsIp(string origin)
        {
            //判断是否为IP
            return Regex.IsMatch(origin, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }

        /// <summary>
        /// 正则：获取IP地址
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>Ip地址</returns>
        public static string RegexGetIp(string origin)
        {
            return Regex.Replace(origin, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$", "");
        }


        /// <summary>
        /// 正则：验证字符串是否是一个mac地址
        /// </summary>
        /// <param name="mac">mac地址，-、:分隔或无分隔</param>
        /// <returns>mac地址的验证</returns>
        public static bool RegexIsMac(string origin)
        {
            //判断是否为IP
            return Regex.IsMatch(origin, @"^([0-9A-Fa-f]{2}([:-]?)){5}[0-9A-Fa-f]{2}$");
        }

        /// <summary>
        /// 正则：获取IP地址
        /// </summary>
        /// <param name="origin">原始字符串</param>
        /// <returns>Ip地址</returns>
        public static string RegexGetMac(string origin)
        {
            return Regex.Replace(origin, @"^([0-9A-Fa-f]{2}([:-]?)){5}[0-9A-Fa-f]{2}$", "");
        }
        #endregion
    }
}
